(* Cardigan Compiler *)
(*
    Reads in a Cardigan source file and compiles it
    to a java source file.
    
    For now, the .java file will just print the contents of the
    .crd file. We'll have to rewrite the "compile" function to
    actually call the compiler once there is a compiler to call.
   
    Ex.
    
    $ echo "Hello Cardigan" > hello.crd
    $ ocamlc -o cardigan cardigan.ml
    $ ./cardigan hello.crd
    $ javac hello.java
    $ java hello
    Hello Cardigan
    $
*)

open Printf
open Ast

(* This function would be useful in an interpreter, which we're probably not building. See string_of_stmt.
let eval = function 
    Int(x) -> x  *)

let string_of_literal = function
    Int(x)      -> string_of_int x
|   String(x)   -> x
|   Float(x)    -> string_of_float x
|   Bool(x)     -> string_of_bool x


(* given an expr, evaluate it and return a string representing the result *)
let rec string_of_expr = function
    Literal(x)  -> string_of_literal x
|   Id(x)       -> x
|   ParenExpr(x)-> string_of_expr x
|   UnaryNegInt(x) -> string_of_int (-1*x)
|   _  -> "unknown type" 

(* given a stmt, evaluate it and return a string representing the result *)
let string_of_stmt = function 
    Expr(y) -> string_of_expr y
|   _  -> "unknown type" 

let string_of_program = function
    _   -> "a program"

let compile = fun source class_name ->
    (* Compile function inserts compiled code into a java class *)
    (* sprintf ("public class %s{\n\tpublic static void main(String[] args){\n\t\tSystem.out.println(\"%s\");\n\t}\n}\n") class_name source *) 
    let lexbuf = Lexing.from_string source in
    let tree = Parser.program Scanner.token lexbuf in
    let result = string_of_program tree in
    ignore (print_endline result); result
;;


let get_source = fun filename ->
    (* Reads in the cardigan source file as a string *)
    (* This is sutable to pass to Lexing.from_string *)
    let source_file = open_in filename in 
    let source_len = in_channel_length source_file in
    let source = String.create source_len in
    really_input source_file source 0 source_len;
    close_in source_file;
    
    (* Trim trailing whitespace. *)
    (* We may need to leave this in once the interpreter is hooked up *)
    String.trim source
;;


let strip_extension = fun full ->
    (* Returns the filename with the extension stripped *)
    let idx = String.index full '.' in
    String.sub full 0 idx
;;


let string_of_expr = function
    Int x -> string_of_int x
|   _      -> "Implement str"

let _ = 
    (* Determine the filename without extension *) 
    let filename = strip_extension Sys.argv.(1) in 

    (* Read in the cardigan source code *)
    let cardigan_source = get_source (filename ^ ".crd") in
    
    (* Compile the cardigan source into java *)
    let java_source = compile cardigan_source filename in
    
    (* Write the compiled code to a .java file *)  
    let target = open_out (filename ^ ".java") in output_string target java_source; 
    close_out target
;;

